#include "PhysicsLayer.h"
#include "config.h"
#include "GameScene.h"

b2World * PhysicsLayer::pWorld = NULL;

PhysicsLayer::PhysicsLayer()
: debugDraw(PTM_RATIO)
, pBackgroundLayer(NULL)
, pGameLayerManager(NULL)
, pPlayer(NULL)
{
  uint32 flags = 0;
  flags += b2Draw::e_shapeBit;
  flags += b2Draw::e_jointBit;
  flags += b2Draw::e_aabbBit;
  flags += b2Draw::e_pairBit;
  flags += b2Draw::e_centerOfMassBit;
  debugDraw.SetFlags(flags);
}

PhysicsLayer::~PhysicsLayer()
{
/*  if (pWorld)
    delete pWorld;*/
}

PhysicsLayer * PhysicsLayer::create()
{
  PhysicsLayer * pLayer = new PhysicsLayer();
  if (pLayer && pLayer->init())
  {
    pLayer->autorelease();
    return pLayer;
  }
  else
  {
    CC_SAFE_DELETE(pLayer);
    return NULL;
  }
}

bool PhysicsLayer::init()
{
  do
  {
    CC_BREAK_IF(!CCLayer::init());

    createWorld();

    topographyManager.init(this, pWorld);

    pPlayer = Player::create(pWorld);
    addChild(pPlayer);
    pPlayer->setPlayerEventListener(this);

    scheduleUpdate();

    setTouchEnabled(true);
    setTouchMode(kCCTouchesOneByOne);
    return true;
  }
  while(0);
  return false;
}

void PhysicsLayer::draw()
{
    CCLayer::draw();

    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );

    kmGLPushMatrix();

    pWorld->DrawDebugData();

    kmGLPopMatrix();
}

void PhysicsLayer::update(float dt)
{
  int offset = -(pPlayer->getBody()->GetPosition().x - PLAYER_POS_OFFSET_X) * PTM_RATIO;
  pBackgroundLayer->setPositionX(offset);
  setPositionX(offset);

  pGameLayerManager->refreshScore(DISTANCE, -offset/ PTM_RATIO);

  topographyManager.update(pPlayer->getBody());

  int velocityIterations = 8;
  int positionIterations = 1;

  float stepTime = 1.0f/60.0f;
  pWorld->Step(stepTime, velocityIterations, positionIterations);
}

void PhysicsLayer::setBackgroundLayer(BackgroundLayer * pBackgroundLayer)
{
  this->pBackgroundLayer = pBackgroundLayer;
}

void PhysicsLayer::createWorld()
{
  if (!pWorld)
  {
    b2Vec2 gravity;
    gravity.Set(0.0f, -10.0f);
    pWorld = new b2World(gravity);
  }

  pWorld->SetAllowSleeping(true);

  pWorld->SetContinuousPhysics(true);

  pWorld->SetDebugDraw(&debugDraw);

  pWorld->SetContactListener(&contactListener);
  pWorld->SetContactFilter(&contactListener);
}

bool PhysicsLayer::ccTouchBegan(CCTouch * pTouch, CCEvent * pEvent)
{
  CCPoint point = pTouch->getLocation();
  if (point.x < SCREEN_WIDTH/2)
  {
    pPlayer->action(Player::JUMP);
  }
  else
  {
    pPlayer->action(Player::ROUND);
  }
  return true;
}

void PhysicsLayer::ccTouchEnded(CCTouch * pTouch, CCEvent * pEvent)
{
  CCPoint point = pTouch->getLocation();
  if (point.x < SCREEN_WIDTH/2)
  {
  }
  else
  {
    pPlayer->action(Player::RUN);
  }
}

void PhysicsLayer::setGameLayerManager(GameLayerManager * pGameLayerManager)
{
  this->pGameLayerManager = pGameLayerManager;
}

void PhysicsLayer::onPlayerDead()
{
  pGameLayerManager->endGame();
}

void PhysicsLayer::setPropCount(int count)
{
  pGameLayerManager->refreshScore(PROP_COUNT, count);
}

void PhysicsLayer::restart()
{
  pPlayer->restart();
  topographyManager.restart(pWorld);
}
